package cn.com.fig.sso;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;

import com.alibaba.druid.support.json.JSONUtils;
import org.apache.commons.lang3.StringUtils;

/**
 * <p>
 * Title: TokenGenerator
 * </p>
 * <p>
 * Description: 令牌生成器
 * </p>
 */
public class TokenGenerator {

    private static final TokenGenerator INSTANCE = new TokenGenerator();
    private TokenGenerator() {
    }

    /**
     * @return 实例
     */
    public static TokenGenerator getInstance() {
        return INSTANCE;
    }

    /**
     * 生成
     *
     * @param yhdm
     *            用户ID
     * @param yxq
     *            token有效期,毫秒，读取web.xml中配置
     * @return 令牌
     * JWT的构成:第一部分我们称它为头部（header),第二部分我们称其为载荷（payload, 类似于飞机上承载的物品)，第三部分是签证（signature)
     */
    public String gen(String yhdm,String yxq,String sessionId) {
    	Map<String,String> header = new HashMap<String,String>();
    	Map<String,String> payload = new HashMap<String,String>();
//    	header
    	header.put("typ", "JWT");
    	header.put("alg", "HS256");
    	String hh = new String(Base64.encodeBase64(JSONUtils.toJSONString(header).getBytes()));
    	
//       payload
        long curtime = System.currentTimeMillis();      
        payload.put("second", String.valueOf(curtime));//当前时间
        payload.put("yxq", yxq);//有效期
        payload.put("userId", yhdm);//userId
        payload.put("sessionid", sessionId);//sessionid
        String pp = new String(Base64.encodeBase64(JSONUtils.toJSONString(payload).getBytes()));
        
//        signature
        int hash = yhdm.hashCode();
        BigDecimal bigd = new BigDecimal(curtime);
        bigd = bigd.multiply(new BigDecimal(String.valueOf(hash)));
        bigd = bigd.multiply(new BigDecimal("7"));
        String second = bigd.toString();
        second = new StringBuffer(second).reverse().toString();
        payload.put("second", second);//当前时间        
        String temp = hh + "." + new String(Base64.encodeBase64(JSONUtils.toJSONString(payload).getBytes()));
        String ss = DigestUtils.sha256Hex(temp);
        
        String token = pp +"." + ss ;
        return token;
    }

    /**
     * 检查客户端token是否有效
     * @param yhdm
     * @param token
     * @return
     */
    public boolean checkToken(String yhdm ,String token){
        if(token == null)
            return false;
        String[] v = StringUtils.split(token,".");
        //        token应该由2部分组成
        if(v.length != 2)
            return false;

        String pp = v[0];
        String ss = v[1];
        Map payload = (Map)JSONUtils.parse(new String(Base64.decodeBase64(pp)));
        String userId = (String)payload.get("userId");
        String yxq = (String)payload.get("yxq");//cookie有效期，以分为单位
        long curtime = Long.parseLong((String)payload.get("second"));
//        判断token中userid和当前用户是否一致
        if(!yhdm.equals(userId))
            return false;
//        判断token是否过期
        if(System.currentTimeMillis() > (curtime + Long.parseLong(yxq)*60*1000))
            return false;

        int hash = yhdm.hashCode();
        BigDecimal bigd = new BigDecimal(curtime);
        bigd = bigd.multiply(new BigDecimal(String.valueOf(hash)));
        bigd = bigd.multiply(new BigDecimal("7"));
        String second = bigd.toString();
        second = new StringBuffer(second).reverse().toString();
        payload.put("second", second);//当前时间
        Map<String,String> header = new HashMap<String,String>();
        //    	header
        header.put("typ", "JWT");
        header.put("alg", "HS256");
        String hh = new String(Base64.encodeBase64(JSONUtils.toJSONString(header).getBytes()));
        String temp = hh + "." + new String(Base64.encodeBase64(JSONUtils.toJSONString(payload).getBytes()));
        String s1 = DigestUtils.sha256Hex(temp);

//        加密算法验证
        if(!s1.equals(ss))
            return false;

        return true;
    }
}
